#include "Plane3d.h"

Plane3d::Plane3d(double i_a, double i_b, double i_c, double i_d) 
  : m_a(i_a), m_b(i_b), m_c(i_c), m_d(i_d)
  {

  }
Plane3d::Plane3d(Point3d i_point, Vector3d i_normal)
  {
  m_a = i_normal.GetX();
  m_b = i_normal.GetY();
  m_c = i_normal.GetZ();
  m_d = -(i_normal.GetX() * i_point.GetX() + i_normal.GetY() * i_point.GetY() + i_normal.GetZ() * i_point.GetZ());
  }

Plane3d::Plane3d(Point3d i_first, Point3d i_second, Point3d i_third)
  {
  double x1, y1, z1;
  i_first.GetAttributes(x1,y1,z1);
  double x2, y2, z2;
  i_second.GetAttributes(x2,y2,z2);
  double x3, y3, z3;
  i_third.GetAttributes(x3,y3,z3);

  m_a = y1*z2 - y1*z3 - y2*z1 + y2*z3 + y3*z1 - y3*z2;
  m_b = -x1*z2 + x1*z3 + x2*z1 - x2*z3 - x3*z1 + x3*z2;
  m_c = x1*y2 - x2*y1 + x3*y1 - x1*y3 + x2*y3 - x3*y2;
  m_d = -x1*y2*z3 + x2*y1*z3 - x3*y1*z2 + x1*y3*z2 - x2*y3*z1 + x3*y2*z1;
  }

Plane3d::Plane3d(Triangle3d i_triangle)
  {
  double x1, y1, z1;
  i_triangle.GetPoint(1).GetAttributes(x1,y1,z1);
  double x2, y2, z2;
  i_triangle.GetPoint(2).GetAttributes(x2,y2,z2);
  double x3, y3, z3;
  i_triangle.GetPoint(3).GetAttributes(x3,y3,z3);

  m_a = y1*z2 - y1*z3 - y2*z1 + y2*z3 + y3*z1 - y3*z2;
  m_b = -x1*z2 + x1*z3 + x2*z1 - x2*z3 - x3*z1 + x3*z2;
  m_c = x1*y2 - x2*y1 + x3*y1 - x1*y3 + x2*y3 - x3*y2;
  m_d = -x1*y2*z3 + x2*y1*z3 - x3*y1*z2 + x1*y3*z2 - x2*y3*z1 + x3*y2*z1;
  }

double Plane3d::GetA()
  {
  return m_a;
  }
double Plane3d::GetB()
  {
  return m_b;
  }
double Plane3d::GetC()
  {
  return m_c;
  }
double Plane3d::GetD()
  {
  return m_d;
  }

bool Plane3d::IsParallel( Plane3d i_plane)
  {
  double a_coef = this->GetA() / i_plane.GetA();
  double b_coef = this->GetB() / i_plane.GetB();
  double c_coef = this->GetC() / i_plane.GetC();
  double d_coef = this->GetD() / i_plane.GetD();

  if( fabs(a_coef - b_coef) < EPS)
    {
    if( fabs(a_coef - c_coef) < EPS)
      {
      if( fabs(a_coef - d_coef) < EPS)
        {
        return false;
        }
      else
        {
        return true;
        }
      }
    else
      {
      return false;
      }
    }
  else
    {
    return false;
    }
  }

bool Plane3d::IsSame( Plane3d i_plane)
  {
  double a_coef = this->GetA() / i_plane.GetA();
  double b_coef = this->GetB() / i_plane.GetB();
  double c_coef = this->GetC() / i_plane.GetC();
  double d_coef = this->GetD() / i_plane.GetD();

  if( fabs(a_coef - b_coef) < EPS)
    {
    if( fabs(a_coef - c_coef) < EPS)
      {
      if( fabs(a_coef - d_coef) < EPS)
        {
        return true;
        }
      else
        {
        return false;
        }
      }
    else
      {
      return false;
      }
    }
  else
    {
    return false;
    }
  }
bool Plane3d::IsPerpendicular( Plane3d i_plane)
  {
  double result = this->GetA() * i_plane.GetA() +
    this->GetB() * i_plane.GetB() +
    this->GetC() * i_plane.GetC();

  if( fabs(result) < EPS) 
    return true;
  else
    return false;
  }

double Plane3d::GetDistanceFromPoint(Point3d i_point)
  {
  double distance = 0;
  double dividend = 0;
  double divider = 0;

  dividend = fabs (this->GetA() * i_point.GetX() +
    this->GetB() * i_point.GetY() +
    this->GetC() * i_point.GetZ() +
    this->GetD());

  divider = sqrt(this->GetA() * this->GetA() + this->GetB() * this->GetB() + this->GetC() * this->GetC());
  distance = dividend / divider;
  return distance;
  }
